<?php
	/**
	  * @package	MyDebuger
	  * @name		CombinationsBuilder
	  * @brief		Clase para generar combinaciones de una lista de elementos
	  * @author		Hermann D. Schimpf <hschimpf@gschimpf.com>
	  * @license	http://opensource.org/licenses/gpl-2.0.php
	  * @date		2009-12-20
	  * @version	0.1.0
  	**/

	class CombinationsBuilder extends MyDebuger implements MyVersions {
		/* version de la clase */
		private static $version			= 0;
		/* subversion de la clase */
		private static $subversion		= 1;
		/* numero de revision de la clase */
		private static $revision		= 0;

		/* elementos a procesar */
		private $elementsList					= Array();
		/* combinaciones resultantes */
		private $combinacionesResultantes	= Array();

		public function __construct($debug = False) {
			/* creamos el padre */
			parent::__construct($debug, __CLASS__, 086);
			/* habilitamos el registro en un fichero */
			$this->enableLog(__CLASS__ . '.log');
		}

		public static final function getVersion() {
			/* retornamos la version actual de la clase */
			return 'v' . self::$version . '.' . self::$subversion . '.' . self::$revision;
		}

		public static function getCombinations($elementsList = Null, $debug = False) {
			try {
				try {
					/* creamos una instancia */
					$getCombinations = new CombinationsBuilder($debug);
					/* verificamos los valores recibidos */
					$getCombinations->verificarValoresRecibidos($elementsList);
					/* almacenamos los elementos recibidos */
					$getCombinations->saveElements($elementsList);
					/* armamos las combinaciones */
					$getCombinations->armarCombinaciones();
					/* retornamos las combinaciones */
					return $getCombinations->getResult();
				} catch (Exception $e) {
					/* capturamos todos los errores y los transformamos en mi excepcion */
					$getCombinations->convertToMyException($e);
				}
			} catch (MyException $e) {
				/* si se produjo una excepcion la manejamos con el metodo 'show' */
				$getCombinations->show($e->getMensaje());
			}
		}

		private function verificarValoresRecibidos($elementsList) {
			/* verificamos si especifico algun valor */
			if ($elementsList === Null)
				/* salimos con una excepcion */
				$this->newException('No se especificaron los elementos a procesar');
			/* verificamos si los elementos se pasaron por medio de un array */
			if (gettype($elementsList) !== 'array')
				/* salimos con una excepcion */
				$this->newException('Los elementos se deben enviar en un array');
		}

		private function saveElements($elementsList) {
			/* almacenamos los elementos recibidos */
			$this->elementsList = $elementsList;
		}

		private function armarCombinaciones() {
			/* creamos una array temporal donde almacenaremos las combinaciones */
			$combinaciones = Array($this->elementsList);
			/* recorremos las interfaces */
			foreach ($this->elementsList AS $interfaz) {
				/* ingresamos a un bucle por la cantidad de elementos */
				for ($i = 0; $i < count($this->elementsList); $i++) {
					/* creamos un array temporal */
					$combinacion = Array();
					/* colocamos el elemento actual en la posicion */
					$combinacion[$i] = $interfaz;
					/* recorremos los elementos */
					foreach ($this->elementsList AS $elementoFaltante) {
						/* verificamos si el elemento existe */
						if (!in_array($elementoFaltante, $combinacion)) {
							/* recorremos las posiciones de la combinacion */
							for ($j = 0; $j < count($this->elementsList); $j++) {
								/* verificamos si la posicion esta en uso */
								if (!isset($combinacion[$j])) {
									/* agregamos el elemento */
									$combinacion[$j] = $elementoFaltante;
									/* finalizamos el buqle */
									break;
								}
							}
						}
					}
					/* ordenamos el array */
					ksort($combinacion);
					/* verificamos si la combinacion ya la tenemos */
					if (!in_array($combinacion, $combinaciones))
						/* creamos una combinacion con el elemento actual */
						$combinaciones[] = $combinacion;
				}
			}
			/* almacenamos las combinaciones resultantes */
			$this->combinacionesResultantes = $combinaciones;
		}

		private function getResult() {
			/* retornamos las combinaciones */
			return $this->combinacionesResultantes;
		}
	}
?>